package com.pub.paypal.common.util;

import okhttp3.*;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Configuration
public class HttpUtils {
    private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class);

    // 网关地址
    private static String GATEWAY_ADDR;

    public static void setGATEWAY_ADDR(String gATEWAY_ADDR) {
        GATEWAY_ADDR = gATEWAY_ADDR;
    }

    @Value("${gateway.addr}")
    public void setGatewayAddr(String gatewayAddr) {
        setGATEWAY_ADDR(gatewayAddr);
    }

    public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
    public static final MediaType wwwForm = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");

    private static final OkHttpClient client = new OkHttpClient.Builder()
            .connectTimeout(120, TimeUnit.SECONDS)
            .readTimeout(120, TimeUnit.SECONDS)
            .writeTimeout(120, TimeUnit.SECONDS)
            .build();


    public static String sendInstructions(String imei,String insContent,String timeOut,String custom,String type) {
        // request body
        Map<String, Object> foo = new HashMap<>();
        foo.put("imei", imei);
        foo.put("content", insContent);
        foo.put("timeout", timeOut);//超时时间
        foo.put("custom", custom);//自定义唯一ID
        foo.put("type", type);//指令类型 sync-同步 anysc-异步

        logger.info("发送指令中："+JSONObject.toJSONString(foo));
        try {
            String url = GATEWAY_ADDR+"?"+urlencode(foo);
            String resp = post(url,JSONObject.toJSONString(foo));
            return resp;
        } catch (Exception e) {
            logger.error("指令发送失败："+JSONObject.toJSONString(foo),e);
        }
        return null;
    }


    /**
     *
     * @param url 请求地址
     * @param params 请求参数
     * @param method 请求方法
     * @return 网络请求字符串
     * @throws Exception
     */
    public static String net(String url, Map<String, Object> params, String method) {
        String resp = null;
        try {
            if (method == null || method.equals("GET")) {
                resp = get(url, params);
            } else {
                resp = post(url, JSONObject.toJSONString(params));
            }
        } catch (IOException e) {
            logger.error("url请求异常：",e);
        }
        return resp;
    }


    /**
     * 提交方式，表单
     * @param url 请求地址
     * @param formBody 请求表单
     * @return 网络请求字符串
     * @throws Exception
     */
    public static String netForm(String url, FormBody formBody) {
        String resp = null;
        try {
            resp = postForm(url, formBody);
        } catch (IOException e) {
        }
        return resp;
    }

    public static String post(String url, String json) throws IOException {
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder().url(url).post(body).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    public static String postForm(String url, FormBody formBody) throws IOException {
        OkHttpClient client = new OkHttpClient.Builder().connectTimeout(120, TimeUnit.SECONDS)
                .readTimeout(120, TimeUnit.SECONDS).writeTimeout(120, TimeUnit.SECONDS).build();
        Request request = new Request.Builder().url(url).post(formBody).build();
        Response response = client.newCall(request).execute();
        return response.body().string();
    }

    public static String get(String url, Map<String, Object> params) throws IOException {
        if (!params.isEmpty()) {
            url = url + "?" + urlencode(params);
        }
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(url).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.code() == 200) {
                logger.info("http GET 请求成功; [url={}]", url);
                return response.body().string();
            } else {
                logger.warn("Http GET 请求失败; [errorCode = {} , url={}]", response.code(), url);
            }
        } catch (IOException e) {
            throw new RuntimeException("同步http GET 请求失败,url:" + url, e);
        }
        return null;
    }

    // 将map型转为请求参数型
    public static String urlencode(Map<String, Object> data) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, Object> i : data.entrySet()) {
            try {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue() + "", "UTF-8")).append("&");
            } catch (UnsupportedEncodingException e) {
                logger.error("map型转为请求参数型异常：",e);
            }
        }
        return sb.toString();
    }


    public static String getByStringMap(String url, Map<String,String> params) throws IOException {
        if(!params.isEmpty()) {
            url = url +"?"+urlencodeString(params);
        }
        Request.Builder builder = new Request.Builder();
        Request request = builder.get().url(url).build();
        try {
            Response response = client.newCall(request).execute();
            if (response.code() == 200) {
                logger.info("http GET 请求成功; [url={}]", url);
                return response.body().string();
            } else {
                logger.warn("Http GET 请求失败; [errorCode = {} , url={}]", response.code(), url);
            }
        } catch (IOException e) {
            logger.error("同步http GET 请求失败,url:" + url,e);
        }
        return null;
    }

    //将map型转为请求参数型
    public static String urlencodeString(Map<String,String> data) {
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String,String> i : data.entrySet()) {
            try {
                sb.append(i.getKey()).append("=").append(URLEncoder.encode(i.getValue()+"","UTF-8")).append("&");
            } catch (UnsupportedEncodingException e) {
                logger.error("请求异常", e);
            }
        }
        return sb.toString();
    }


    /**
     * 通过发送http get 请求获取文件资源
     *
     * @param url
     * @param filepath
     * @return
     */
    public static void download(String url, String filepath)throws IOException {
        OkHttpClient client = new OkHttpClient();
        Request req = new Request.Builder().url(url).build();
        Response resp = null;
        FileOutputStream fops= null;
        File imgFile = null;
        try {
            resp = client.newCall(req).execute();
            if (resp.isSuccessful()) {
                ResponseBody body = resp.body();
                InputStream is = body.byteStream();
                byte[] data = readInputStream(is);
                imgFile = new File(URLDecoder.decode(filepath, "utf-8"));
                fops = new FileOutputStream(imgFile);
                fops.write(data);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("Unexpected code: ",resp);
        }finally {
            if (fops != null) {
                fops.close();
            }
        }
    }

    /**
     * 读取字节输入流内容
     *
     * @param is
     * @return
     */
    private static byte[] readInputStream(InputStream is) {
        ByteArrayOutputStream writer = new ByteArrayOutputStream();
        byte[] buff = new byte[1024 * 2];
        int len = 0;
        try {
            while ((len = is.read(buff)) != -1) {
                writer.write(buff, 0, len);
            }
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return writer.toByteArray();
    }
}
